package com.utilities.visualiser.circularContigs;

import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Element;

import com.utilities.dataStructures.Range;
import com.utilities.parsers.coordsParser.ParseCoordsFileParser;
import com.utilities.parsers.coordsParser.ParseEvents;
import com.utilities.parsers.coordsParser.ParseListener;
import com.utilities.visualiser.PrepareXMLFile;

public class CoordVisualiser extends ParseListener implements Comparator<Range> {

	ParseCoordsFileParser fileParser = null;
	ArrayList<ArrayList<Range>> slots = new ArrayList<ArrayList<Range>>();
	String[] colors = {"maroon","red","blue","green","orange", "purple","fuchsia","navy",
			"lime","olive","yellow","teal","aqua","silver","gray","white","black",
			"maroon","red","blue","green","orange", "purple","fuchsia","navy",
			"lime","olive","yellow","teal","aqua","silver","gray","white","black"};
	PrepareXMLFile prepareXMLFile = null;
	Element directScoreFeature = null;
	String radiusAdjustment = null;
	String featureSlotId = null;
	String featureColor = null;
	int maxSlots = 0;
	
	@Override
	public void handleEvent(ParseEvents event) {
		
		try
		{
			switch((ParseEvents.EventTypes)event.getEventType())
			{
				case docStarted : break;
				case docEnded: break;
				case headerRead: 
				{
					break;
				}
				case newEntry: 
				{
					String[] params = fileParser.parseCoordsFileLine((String)event.getSource());
					if (true)
					{
						int refStart = Integer.parseInt(params[0]);
						int refEnd = Integer.parseInt(params[1]);
//						String contigName = params[14];
//						if (params[12].trim().equalsIgnoreCase("-1"))
//						{
//							contigName = contigName + ": reverse"; 
//						}
						Range range = null;
						if (refEnd < refStart)
						{
							range = new Range(refEnd, refStart, true,(String)event.getSource());
						}
						else
						{
							range = new Range(refStart,refEnd,(String)event.getSource());
						}
						boolean included = false;
						for (int i = 0 ; i < slots.size(); i++)
						{
							ArrayList<Range> ranges = slots.get(i);
							for (Range range2 : ranges)
							{
								if (!range2.exclusive(range))
								{
									included = true;
								}
							}
							if (included)
							{
								ranges.add(range);
								slots.set(i, ranges);
							}
						}
						if (!included)
						{
							ArrayList<Range> ranges = new ArrayList<Range>();
							ranges.add(range);
							slots.add(ranges);
						}
					}
					break;
				}
			}
		}
		catch(Exception e)
		{
			e.printStackTrace();
			System.exit(1);
		}
	}
	
	public static void main(String[] args) throws Exception
	{
		args = new String[1];
		args[0] = "Scaffold";
		CoordVisualiser parser = new CoordVisualiser();
		parser.fileParser = new ParseCoordsFileParser();
		parser.fileParser.addListener(parser);
		parser.fileParser.parse(new File("C:/database/454/newData/NewFolder/7328Run1/nucmer.tiles"));
		parser.writeToFile("c:/database/out.output");
		parser.filter();
		parser.writeToFile("c:/database/out4.output");
		parser.prepareXMLFile = new PrepareXMLFile().initialise();
		parser.makeFeatureSlots(parser.initialise("4639675",args), parser.slots.size());
		
		for (int i = 0; i < parser.slots.size(); i++)
		{
			ArrayList<Range> ranges = parser.slots.get(i);
			Collections.sort(ranges, parser);
			for (int j = 0 ; j < ranges.size(); j++)
			{
				Range range = ranges.get(j);
				parser.featureColor = parser.colors[j];
				parser.featureSlotId = "directStrand" + (ranges.size() - j - 1);
				String mouseOver = "Start = " + String.valueOf(range.getLowerLimit())
									+ ", stop = " + String.valueOf(range.getUpperLimit());
				
				String metadata = range.getMetadata();
				String[] params = parser.fileParser.parseCoordsFileLine(metadata);
				boolean isReverse = (params[12].trim().equalsIgnoreCase("-1")) ? true : false;
				String contigName = params[14].trim();
				System.out.println();
				if (isReverse)
					mouseOver = mouseOver + ", reverse query";
				Element feature = null;
				if (range.isReverse())
				{
					feature = parser.prepareXMLFile.createFeature(parser.featureSlotId, parser.featureColor, "counterclockwise-arrow", 
							contigName, null,mouseOver,null,null,null);
				}
				else
				{
					feature = parser.prepareXMLFile.createFeature(parser.featureSlotId, parser.featureColor, "clockwise-arrow", 
							contigName, null,mouseOver,null,null,null);
				}
				parser.prepareXMLFile.createFeatureRange(feature, String.valueOf(range.getLowerLimit()), 
						String.valueOf(range.getUpperLimit()), null);
			}
		}
		parser.prepareXMLFile.writeToFile("c:/database/454/454Annotations.xml");
	}
	
	private void writeToFile(String str) {
		try
		{
			FileWriter fileWriter = new FileWriter(new File(str));
			int i = 0;
			for (ArrayList<Range> list : slots)
			{
				for (Range range : list)
				{
					fileWriter.write(range.getLowerLimit() + "-" + range.getUpperLimit() + " ");
				}
				fileWriter.write("\n");
				i++;
			}
			fileWriter.flush();
			fileWriter.close();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}

	private void filter() 
	{
		for (int i = 0 ; i < slots.size(); i++)
		{
//			System.out.println(i);
			ArrayList<Range> ranges = slots.get(i);
			// whether it is a conflicted range or not
			if (ranges.size() > 1)
			{
				ArrayList<Range> ranges_temp = new ArrayList<Range>();
				for (int j = 0; j < ranges.size() ; j++)
				{
					Range range = ranges.get(j); 
					boolean contains = false;
					// check if it is fully contained in any other in the list
					// transitivity holds here
					for (int k = 0 ; k < ranges.size(); k++)
					{
						if (k != j)
						{
							Range range_temp = ranges.get(k);
							if (range_temp.contains(range))
							{
								contains = true;
								break;
							}
						}
					}
					// check the percentage identity also
					String[] params = fileParser.parseCoordsFileLine(range.getMetadata());
					float percentageIdentity = Float.parseFloat(params[6]);
					if (!(contains && percentageIdentity < 90.00))
					{
						ranges_temp.add(range);
					}
				}
				if (ranges_temp.size() == 0)
				{
					System.err.println("ranges_temp is empty");
				}
				else
				{
					slots.set(i, ranges_temp);
				}
			}
		}
		
		for (int i = 0 ; i < slots.size(); i++)
		{
			System.out.println(i);
			ArrayList<Range> ranges = slots.get(i);
			// whether it is a conflicted range or not
			if (ranges.size() > 1)
			{
				ArrayList<Range> ranges_temp = new ArrayList<Range>();
				for (int j = 0; j < ranges.size() ; j++)
				{
					Range range = ranges.get(j); 
					boolean contains = false;
					// check if it is fully contained in any other in the list
					// transitivity holds here
					for (int k = 0 ; k < ranges.size(); k++)
					{
						if (k != j)
						{
							Range range_temp = ranges.get(k);
							if (range_temp.contains(range))
							{
								String[] params = fileParser.parseCoordsFileLine(range.getMetadata());
								float percentageIdentity1 = Float.parseFloat(params[6]);
								params = fileParser.parseCoordsFileLine(range_temp.getMetadata());
								float percentageIdentity2 = Float.parseFloat(params[6]);
								if (percentageIdentity2 >= percentageIdentity1)
								{
									contains = true;
									break;
								}
							}
						}
					}
					// check the percentage identity also
					
					if (!(contains))
					{
						ranges_temp.add(range);
					}
				}
				if (ranges_temp.size() == 0)
				{
					System.err.println("ranges_temp is empty");
				}
				else
				{
					slots.set(i, ranges_temp);
				}
			}
			if (slots.get(i).size() > maxSlots) maxSlots = slots.get(i).size();
		}
	}

	private PrepareXMLFile initialise(String seqLength, String[] args) throws ParserConfigurationException 
	{
		PrepareXMLFile result = prepareXMLFile.createCGView(seqLength);
//		.createLegend("sideLegend", "upper-right", "SanSerif, plain, 10", "0.8");
//		
//		result = result.createLegendItem("sideLegend", args[0], "SanSerif, plain, 12", true, this.colors[0]);
//		result = result.createLegend("lowerleftlegend", "lower-left", "SanSerif, plain, 9", "0.8")
//		.createLegendItem("lowerleftlegend", "This map was generated using CGView", null, false, null)
//		.createLegend("lowerrightlegend", "lower-right", "SanSerif, plain, 9", "0.8")
//		.createLegendItem("lowerrightlegend", "Work done at D-BSSE ETH Zurich", null, false, null);
		return result;
	}
	
	private PrepareXMLFile makeFeatureSlots(PrepareXMLFile prepareXMLFile, int slots) 
	{
		PrepareXMLFile result = prepareXMLFile;
		for(int i = 0; i <= maxSlots; i++)
		{
			result = result.createFeatureSlots("directStrand" + i, "direct",false);
		}
		return result;
	}

	@Override
	public int compare(Range o1, Range o2) {
		return (o1.length()) - (o2.length());
	}
}
